package com.zmn.oms.business.impl.price;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.zmn.base.price.dubbo.interfaces.calculate.ItemPriceRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.DefaultEcProductQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.oms.business.interfaces.price.PriceTableBService;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.enums.ServiceItemTypeEnum;
import com.zmn.oms.common.enums.TelevisionItmeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.work.modify.CheckQuotationTypeOrderDTO;
import com.zmn.oms.model.dto.work.modify.ServiceItemQueryDTO;
import com.zmn.oms.model.dto.work.modify.ServiceItemResultDTO;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.price_list.*;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述: 价格表
 *
 * @author yangjiangming
 * @date 2019-04-17 19:06
 */
@Service
public class PriceTableBServiceImpl implements PriceTableBService {

    private Logger logger = LoggerFactory.getLogger(PriceTableBServiceImpl.class);

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ProductForeignListRemoteService productForeignListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ItemPriceRemoteService itemPriceRemoteService;

    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderProductService orderProductService;
    @Autowired
    private ServItemBService servItemBService;

    @NacosValue(value = "${zmn.price.pilot.cityId:500100}",autoRefreshed = true)
    private String pilotCityId;

    @NacosValue(value = "${zmn.price.special.brandId:1006,1005}",autoRefreshed = true)
    private String specialBrandId;



    private <T> T getRPCResult(ResponseDTO<T> responseDTO) throws OmsBaseException {
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getMessage());
        }
        return responseDTO.getData();
    }

    /**
     * 根据城市，获取产品价格表
     *
     * @param productId
     * @param cityId
     * @param channelId
     * @param bizType
     * @return
     * @throws OmsBaseException
     */
    @Override
    public PriceListVO getProductPriceTable(Integer productId, Integer cityId, Integer channelId, Integer bizType, Integer brandId, Integer tariffType, Long orderId, Long workId, Integer type,Integer plat, List<Integer> itemIdList, Integer productCategId) throws OmsBaseException {
        PriceListVO priceListVO = new PriceListVO();

        // 处理itemList中为null的数据
        if (CollectionUtil.isNotNullOrEmpty(itemIdList)) {
            itemIdList.removeIf(Objects::isNull);
        }

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        List<ProductBaseDRO> productDROS = getRPCResult(productRemote);

        boolean isUpdatePage = Objects.nonNull(orderId) && Objects.nonNull(workId);
        Integer tariffId = null;
        Integer servItemType = null;
        Integer finalPrice = null;
        Integer companyId = null;
        Integer masterId = null;
        Integer beforeServItemType = null;

        if (isUpdatePage) {
            // 获取前台产品id
            Integer showProductId = null;
            if (Objects.equals(productDROS.get(0).getShowType(), BaseProductConsts.EC_SHOW_TYPE)) {
                showProductId = productId;
            } else if (Objects.equals(productDROS.get(0).getShowType(), BaseProductConsts.ERP_SHOW_TYPE)) {
                DefaultEcProductQuery defaultEcProductQuery = new DefaultEcProductQuery();
                defaultEcProductQuery.setProductIdList(Lists.newArrayList(productId));
                defaultEcProductQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
                ResponseDTO<List<ProductBaseDRO>> showProductRemote = productForeignListRemoteService.listEcErpProductByQuery(defaultEcProductQuery);
                if (CollectionUtil.isNotNullOrEmpty(showProductRemote.getData())) {
                    showProductId = showProductRemote.getData().get(0).getProductId();
                }
            }

            OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
            boolean isShowProductIdChanged = !Objects.equals(orderWork.getShowProductId(), showProductId);
            boolean channelChanged = !NumberUtil.isNullOrZero(orderWork.getChannelId()) && !Objects.equals(orderWork.getChannelId(), channelId);
            boolean cityChanged = !NumberUtil.isNullOrZero(orderWork.getCityId()) && !Objects.equals(orderWork.getCityId(), cityId);
            boolean isRework = Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK) && Objects.equals(bizType, OrderConsts.ORDER_TYPE_REWORK);
            List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderId);
            tariffId = orderProducts.get(0).getTariffId();
            servItemType = orderWork.getServItemType();
            finalPrice = orderWork.getFinalPrice();
            if ((isShowProductIdChanged || channelChanged || cityChanged) && !isRework) {
                tariffId = null;
                servItemType = null;
                finalPrice = null;
            }

            companyId = orderWork.getCompanyId();
            masterId = orderWork.getMasterId();
            beforeServItemType = orderWork.getServItemType();
        }

        if (NumberUtil.isNullOrZero(servItemType)) {
            CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO = CheckQuotationTypeOrderDTO
                    .builder()
                    .type(type)
                    .sourceType(OrderConsts.ORDER_SOURCE_TYPE_NORMAL)
                    .productId(productId)
                    .platWork(plat)
                    .cityId(cityId)
                    .channelId(channelId)
                    .bizType(bizType)
                    .companyId(companyId)
                    .masterId(masterId)
                    .beforeServItemType(beforeServItemType)
                    .build();
            servItemType = servItemBService.getServItemType(checkQuotationTypeOrderDTO);
        }

        priceListVO.setServTypeName(this.getServTypeName(servItemType, finalPrice));
        ServiceItemQueryDTO serviceItemQueryDTO = ServiceItemQueryDTO
                .builder()
                .servItemType(servItemType)
                .productId(productId)
                .channelId(channelId)
                .bizType(bizType)
                .brandId(brandId)
                .cityId(cityId)
                .tariffId(tariffId)
                .filterNullPrice(false)
                .searchAdditionItem(true)
                .itemIdList(itemIdList)
                .build();
        List<ServiceItemResultDTO> items = servItemBService.listServiceItem(serviceItemQueryDTO);

        if (CollectionUtil.isNotNullOrEmpty(items) && NumberUtil.isNotNullOrZero(productCategId)) {
            items = items.stream().filter(item -> Objects.equals(item.getCategId(), productCategId)).collect(Collectors.toList());
        }

        Map<Integer, List<ServiceItemResultDTO>> collect = null;
        String productName = null;
        try {
            //试点城市集合
            List<String> pilotCityIds = Arrays.asList(pilotCityId.split(","));
            //特殊品牌
            List<String> specialBrandIds = Arrays.asList(specialBrandId.split(","));

            List<Integer> itemIds = items.stream().map(ServiceItemResultDTO::getItemId).collect(Collectors.toList());

            logger.info("服务项数据 items={}",JSON.toJSONString(items));

            //如果是试点城市并且是特殊品牌
            if(itemIds.contains(TelevisionItmeEnum.SPECIAL_ITEM.getType()) && pilotCityIds.contains(cityId.toString()) && specialBrandIds.contains(brandId.toString())){
                items = items.stream().filter(e -> !Objects.equals(e.getItemId(), TelevisionItmeEnum.DEFAULT_ITEM.getType()) && !Objects.equals(e.getItemId(),TelevisionItmeEnum.GENERAL_ITEM.getType())).collect(Collectors.toList());
            }else if(itemIds.contains(TelevisionItmeEnum.GENERAL_ITEM.getType()) && pilotCityIds.contains(cityId.toString()) && !specialBrandIds.contains(brandId.toString())){
                //如果是试点城市不是特殊品牌
                items = items.stream().filter(e -> !Objects.equals(e.getItemId(),TelevisionItmeEnum.DEFAULT_ITEM.getType()) && !Objects.equals(e.getItemId(),TelevisionItmeEnum.SPECIAL_ITEM.getType())).collect(Collectors.toList());
            }else {
                items = items.stream().filter(e -> !Objects.equals(e.getItemId(),TelevisionItmeEnum.GENERAL_ITEM.getType()) && !Objects.equals(e.getItemId(),TelevisionItmeEnum.SPECIAL_ITEM.getType())).collect(Collectors.toList());
            }
            collect = items.stream().collect(Collectors.groupingBy(ServiceItemResultDTO::getItemCategId));
            productName = productDROS.get(0).getProductName();
        } catch (Exception e) {
            throw new OmsBaseException(StatusConsts.STATUS_ERROR, "Query data error, please check the parameters");
        }

        priceListVO.setProductId(productId);
        priceListVO.setProductName(productName);
        List<PriceVO> priceVOList = new ArrayList<>();
        List<PriceVO> additionalItemsPriceList = new ArrayList<>();
        // 按照项目类型分组完毕
        collect.forEach((categId, itemDROS) -> {
            Map<String, List<ServiceItemResultDTO>> ItemMap = itemDROS.stream().collect(Collectors.groupingBy(ServiceItemResultDTO::getItemName));
            List<PriceItemVO> itemVOS = new ArrayList<>();
            // 按照分组处理
            ItemMap.forEach((itemName, itemDRO) -> {
                //处理最内层
                List<ServiceItemVO> servItems = itemDRO.stream()
                        .map(servServiceItemDRO -> new ServiceItemVO(servServiceItemDRO.getProductName(), servServiceItemDRO.getProductSort(), servServiceItemDRO.getItemName(), servServiceItemDRO.getPrice(), servServiceItemDRO.getUnit(),
                                servServiceItemDRO.getNegotiableMinPrice(), servServiceItemDRO.getNegotiableMaxPrice()))
                        .collect(Collectors.toList());
                Collections.sort(servItems, Comparator.comparing(ServiceItemVO::getBackProductSort));
                PriceItemVO priceItemVO = new PriceItemVO(itemName, servItems);
                itemVOS.add(priceItemVO);
            });
            String categName = itemDROS.get(itemDROS.size() - 1).getItemCategName();
            Integer sort = Optional.ofNullable(itemDROS.get(itemDROS.size() - 1).getCategSort()).orElse(1);
            PriceVO priceVO = new PriceVO(categId, categName, itemVOS, sort, itemDROS.size());
            if (Objects.equals(categId, ServiceItemTypeEnum.ADDITION_ITEM.getType())) {
                additionalItemsPriceList.add(priceVO);
                return;
            }
            priceVOList.add(priceVO);
        });

        Collections.sort(priceVOList, Comparator.comparing(PriceVO::getSort));

        logger.info("服务项目返回数据-------- {}", JSON.toJSONString(priceVOList));
        priceListVO.setPriceList(priceVOList);
        priceListVO.setAdditionalItemsPriceList(additionalItemsPriceList);

        return priceListVO;
    }

    /**
     * 根据城市，获取产品价格表
     * @param productId
     * @param cityId
     * @param channelId
     * @param bizType
     * @return
     * @throws OmsBaseException
     */
    @Override
    public FaultPriceListVO getFaultPriceTable(Integer productId, Integer cityId, Integer channelId, Integer bizType, Integer brandId) throws OmsBaseException {
        CheckQuotationTypeOrderDTO build = CheckQuotationTypeOrderDTO
                .builder()
                .bizType(bizType)
                .channelId(channelId)
                .cityId(cityId)
                .productId(productId)
                .build();
        Integer servItemType = servItemBService.getServItemType(build);
        ServiceItemQueryDTO serviceItemQueryDTO = ServiceItemQueryDTO
                .builder()
                .channelId(channelId)
                .cityId(cityId)
                .productId(productId)
                .bizType(bizType)
                .brandId(brandId)
                .servItemType(servItemType)
                .build();
        List<ServiceItemResultDTO> serviceItemResultDTOList = servItemBService.listServiceItem(serviceItemQueryDTO);

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        ResponseDTO<List<ProductBaseDRO>> productResponse = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        List<ProductBaseDRO> ProductDROS = getRPCResult(productResponse);
        String productName = ProductDROS.get(0).getProductName();

        FaultPriceListVO priceListVO = new FaultPriceListVO();
        priceListVO.setProductId(productId);
        priceListVO.setProductName(productName);

        List<FaultPriceVO> priceVOList = this.processServiceItem(serviceItemResultDTOList);
        logger.info("故障项目返回数据--------",JSON.toJSONString(priceVOList));
        priceListVO.setPriceList(priceVOList);

        return priceListVO;
    }

    private List<FaultPriceVO> processServiceItem(List<ServiceItemResultDTO> faults) throws OmsBaseException {
        Map<Integer, List<ServiceItemResultDTO>> collect = null;

        List<FaultPriceVO> priceVOList = new ArrayList<>();
        try {
            collect = faults.stream().collect(Collectors.groupingBy(ServiceItemResultDTO::getItemCategId));
        } catch (Exception e) {
            throw new OmsBaseException(StatusConsts.STATUS_ERROR, "Query data error, please check the parameters");
        }
        collect.forEach((categId, itemDROS) -> {
            //处理最内层 status返回的故障项均为可用服务项，无需过滤

            Map<String, List<ServiceItemResultDTO>> ItemMap = itemDROS.stream().collect(Collectors.groupingBy(ServiceItemResultDTO::getItemName));
            List<FaultGroupVO> groupVOS = new ArrayList<>();
            ItemMap.forEach((itemName, DROS) -> {
                List<FaultItemVO> faultItems = DROS.stream()
                        .map(itemDRO -> new FaultItemVO(
                                itemDRO.getProductName(),
                                itemDRO.getProductSort(),
                                itemDRO.getItemName(),
                                itemDRO.getPrice(),
                                itemDRO.getUnit(),
                                itemDRO.getItemCategName(),
                                itemDRO.getNegotiableMinPrice(),
                                itemDRO.getNegotiableMaxPrice()))
                        .collect(Collectors.toList());
                Collections.sort(faultItems, Comparator.comparing(FaultItemVO::getBackProductSort));
                //处理中间层
                FaultGroupVO groupVO = new FaultGroupVO(itemName, faultItems);
                groupVOS.add(groupVO);
            });
            String categName = itemDROS.get(itemDROS.size() - 1).getItemCategName();
            Integer sort = Optional.ofNullable(itemDROS.get(itemDROS.size() - 1).getCategSort()).orElse(1);
            FaultPriceVO priceVO = new FaultPriceVO(categId, categName, groupVOS, sort, itemDROS.size());
            priceVOList.add(priceVO);
        });

        Collections.sort(priceVOList, Comparator.comparing(FaultPriceVO::getSort));

        return priceVOList;
    }

    private String getServTypeName(Integer servType, Integer finalPrice) {
        if (Objects.equals(finalPrice, GlobalConsts.YES)) {
            return "一口价价格表";
        }
        switch (servType) {
            case OrderConsts.SERVICE_ITEM_TYPE_ORDER:
                return "价格表";
            case OrderConsts.SERVICE_ITEM_TYPE_FAULT:
                return "计价器价格表";
            case OrderConsts.SERVICE_ITEM_TYPE_ADVANCE_PAY:
                return "提前付价格表";
            case OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE:
                return "计价器3.0价格表";
            case OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE:
                return "一口价价格表";
            default:
                return "价格表";
        }
    }

}
